import akshare as ak
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
import os
import json

# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

def load_local_data():
    """
    从本地加载已有的数据
    """
    if os.path.exists('sector_data_cache.csv'):
        try:
            # 读取本地缓存数据
            cached_data = pd.read_csv('sector_data_cache.csv')
            # 将日期列转换为datetime类型
            cached_data['last_updated'] = pd.to_datetime(cached_data['last_updated'])
            return cached_data
        except Exception as e:
            print(f"读取本地缓存数据时出错: {e}")
            return pd.DataFrame()
    return pd.DataFrame()

def save_local_data(df):
    """
    将数据保存到本地
    """
    try:
        df.to_csv('sector_data_cache.csv', index=False)
        print("数据已保存到本地缓存")
    except Exception as e:
        print(f"保存本地缓存数据时出错: {e}")

def get_sector_performance():
    """
    获取A股各大板块近一年内涨跌幅数据，并列出前十名
    """
    # 获取行业板块数据
    sector_data = ak.stock_board_industry_name_em()
    
    # 获取当前日期和一年前的日期
    end_date = datetime.now().strftime('%Y%m%d')
    start_date = (datetime.now() - timedelta(days=365)).strftime('%Y%m%d')
    
    print(f"统计周期: {start_date} 到 {end_date}")
    
    # 尝试加载本地缓存数据
    cached_data = load_local_data()
    
    # 存储各板块涨跌幅数据
    sector_changes = []
    
    # 遍历各板块获取历史数据
    for index, row in sector_data.iterrows():
        try:
            sector_name = row['板块名称']
            sector_code = row['板块代码']
            
            # 检查是否有本地缓存且数据是最新的
            if not cached_data.empty:
                cached_row = cached_data[
                    (cached_data['板块名称'] == sector_name) & 
                    (cached_data['板块代码'] == sector_code)
                ]
                
                if not cached_row.empty and \
                   cached_row.iloc[0]['last_updated'].date() == datetime.now().date():
                    # 使用缓存数据
                    sector_changes.append({
                        '板块名称': sector_name,
                        '板块代码': sector_code,
                        '涨跌幅(%)': cached_row.iloc[0]['涨跌幅(%)'],
                        '起始价格': cached_row.iloc[0]['起始价格'],
                        '结束价格': cached_row.iloc[0]['结束价格'],
                        'last_updated': cached_row.iloc[0]['last_updated']
                    })
                    print(f"已使用缓存数据: {sector_name}")
                    continue
            
            # 获取板块历史数据
            historical_data = ak.stock_board_industry_hist_em(
                symbol=sector_name, 
                start_date=start_date, 
                end_date=end_date, 
                adjust=""
            )
            
            if not historical_data.empty and len(historical_data) > 0:
                # 确保数据按日期排序
                historical_data = historical_data.sort_values('日期')
                
                # 计算涨跌幅
                start_price = float(historical_data.iloc[0]['收盘'])
                end_price = float(historical_data.iloc[-1]['收盘'])
                change_percent = ((end_price - start_price) / start_price) * 100
                
                sector_changes.append({
                    '板块名称': sector_name,
                    '板块代码': sector_code,
                    '涨跌幅(%)': round(change_percent, 2),
                    '起始价格': round(start_price, 2),
                    '结束价格': round(end_price, 2),
                    'last_updated': datetime.now()
                })
                
                print(f"已处理: {sector_name} 涨跌幅: {round(change_percent, 2)}%")
            
        except Exception as e:
            print(f"处理 {sector_name} 时出错: {e}")
            continue
    
    # 转换为DataFrame并排序
    df = pd.DataFrame(sector_changes)
    df = df.sort_values('涨跌幅(%)', ascending=False).reset_index(drop=True)
    
    # 保存到本地缓存
    save_local_data(df)
    
    # 创建可视化图表
    create_visualization(df)
    
    return df

def create_visualization(df):
    """
    使用seaborn创建可视化表格
    """
    # 获取当前日期用于标题显示和文件名
    current_date = datetime.now().strftime('%y-%m-%d')
    current_date_dir = datetime.now().strftime('%Y-%m-%d')
    file_date = datetime.now().strftime('%Y%m%d')
    
    # 创建以日期命名的目录来保存图表
    output_dir = f'charts/{current_date_dir}'
    os.makedirs(output_dir, exist_ok=True)
    
    # 创建图表
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 16))
    
    # 设置整体标题，包含日期信息
    fig.suptitle(f'A股各大板块近一年涨幅前十名 ({current_date})', fontsize=16, fontweight='bold', y=0.98)
    
    # 绘制涨幅前十名表格
    top_10 = df.head(10)
    
    # 创建表格数据
    table_data_top = top_10[['板块名称', '板块代码', '涨跌幅(%)', '起始价格', '结束价格']].round(2)
    
    # 绘制表格
    table1 = ax1.table(cellText=table_data_top.values,
                       colLabels=table_data_top.columns,
                       cellLoc='center',
                       loc='center',
                       bbox=[0, 0, 1, 0.9])
    
    # 设置表格样式
    table1.auto_set_font_size(False)
    table1.set_fontsize(10)
    table1.scale(1, 2)
    
    # 设置表头样式
    for i in range(len(table_data_top.columns)):
        table1[(0, i)].set_facecolor('#4CAF50')
        table1[(0, i)].set_text_props(weight='bold', color='white')
    
    ax1.axis('off')
    
    # 绘制跌幅前十名表格（实际上是增长幅度最小的）
    bottom_10 = df.tail(10)
    ax2.set_title(f'A股各大板块近一年涨幅后十名 ({current_date})', fontsize=14, pad=60)
    
    # 创建表格数据
    table_data_bottom = bottom_10[['板块名称', '板块代码', '涨跌幅(%)', '起始价格', '结束价格']].round(2)
    
    # 绘制表格
    table2 = ax2.table(cellText=table_data_bottom.values,
                       colLabels=table_data_bottom.columns,
                       cellLoc='center',
                       loc='center',
                       bbox=[0, 0, 1, 1.1])  # 调整表格大小，为标题留出空间
    
    # 设置表格样式
    table2.auto_set_font_size(False)
    table2.set_fontsize(10)
    table2.scale(1, 2)
    
    # 设置表头样式
    for i in range(len(table_data_bottom.columns)):
        table2[(0, i)].set_facecolor('#F44336')
        table2[(0, i)].set_text_props(weight='bold', color='white')
    
    ax2.axis('off')
    
    # 调整布局并保存图表到带日期的目录中，文件名也包含日期
    plt.tight_layout()
    plt.subplots_adjust(hspace=0.3)  # 增加子图间的垂直间距
    plt.savefig(f'{output_dir}/sector_performance_ranking_{file_date}.png', dpi=300, bbox_inches='tight')
    plt.show()
    
    print(f"\n图表已保存为 {output_dir}/sector_performance_ranking_{file_date}.png")

if __name__ == "__main__":
    result_df = get_sector_performance()